package service

import (
	"context"
	"errors"
	"fmt"
	"gin-luban-server/global"
	"gin-luban-server/model"
	"gin-luban-server/model/request"
	"go.uber.org/zap"
	"gorm.io/gorm"
	"strings"
)


//@author: heyibo
//@function: CreateDeployAppConfigure
//@description: 创建应用的配置信息
//@param: applyConfigure DeployAppConfigure
//@return: err error, applyConfigure model.DeployAppConfigure

func CreateDeployAppConfigure(data request.DeployAppConfigureFrom)(err error)  {
	configure := model.DeployAppConfigure{AppsName: data.AppsName,ProjectCode:data.ProjectCode,PackageName: data.PackageName,AppsJobName: data.AppsJobName,BranchName: data.BranchName,
		AppsPort: data.AppsPort,HealthCheck: data.HealthCheck,AppsType: data.AppsType,DeployEnv: data.DeployEnv,DeployPath: data.DeployPath,
		BuildPath: data.BuildPath,BuildRun: data.BuildRun,DeployRun: data.DeployRun,ServerIdc: data.ServerIdc}
	if data.AppsType == "common" || data.AppsType == "apk"{
		if !errors.Is(global.GVA_DB.Where("apps_job_name =  ?", configure.AppsJobName).First(&model.DeployAppConfigure{}).Error, gorm.ErrRecordNotFound) {
			return errors.New("存在相同应用Job名称")
		}
		configure.DeployStatus = "0"
		return global.GVA_DB.Create(&configure).Error
	}
	if len(data.VirtualCodeInfos) == 0 {
        return errors.New("没有选择服务器")
	}
	tx :=global.GVA_DB.Begin()
	if !errors.Is(global.GVA_DB.Where("apps_job_name =  ?", configure.AppsJobName).First(&model.DeployAppConfigure{}).Error, gorm.ErrRecordNotFound) {
		return errors.New("存在相同应用Job名称")
	}
	configure.DeployStatus = "0"
	if err = global.GVA_DB.Create(&configure).Error;err !=nil {
		  tx.Rollback()
		  return err
	}
	virtual :=request.DeployAppVirtualFrom{AppsJobName: data.AppsJobName,VirtualCodeInfos: data.VirtualCodeInfos}
	if err =UpdateDeployAppVirtual(virtual);err != nil {
		  tx.Rollback()
		  return err
	}
	tx.Commit()
    return err
}


//@author: heyibo
//@function: DeleteDeployAppConfigure
//@description: 删除应用的配置信息
//@param: id ,apply model.DeployAppConfigure
//@return: err error
func DeleteDeployAppConfigure(id float64) (err error) {
	// 通过ID获取相关数据
	var appConfig model.DeployAppConfigure
	var appJenkinsConfig model.DeployAppJenkins
	err = global.GVA_DB.Where("id = ? ",id).First(&appConfig).Error

	// 2. 通过所在IDC 获取jenkins地址信息
	var jenkinsConfig model.SysBasicConfigure
	err = global.GVA_DB.Where("purpose = ? AND server_idc = ?","jenkins",appConfig.ServerIdc).First(&jenkinsConfig).Error
	if err != nil {
		return errors.New("基础配置表查询失败！")
	}

	//事务
	// 1. 删除jenkins表数据
	// 2. 删除应用 configure表数据
	// 3. 删除job
	tx := global.GVA_DB.Begin()

	err = tx.Where("id = ?", id).Delete(&appConfig).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	err = tx.Where("apps_job_name = ?", appConfig.AppsJobName).Delete(&appJenkinsConfig).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	// 3. 删除jenkins job
	ctx := context.Background()
	jenkinsClient, err := jenkinsInit(jenkinsConfig, ctx)
	if  err != nil {
		global.GVA_LOG.Error("jenkins 初始化失败", zap.Any("err", err))
		tx.Rollback()
		return  err
	}

	_ , err =jenkinsClient.DeleteJob(ctx, appConfig.AppsJobName)
	if  err != nil {
		if err.Error() != "404"  {
			global.GVA_LOG.Error("jenkins JOB删除失败", zap.Any("err", err))
			tx.Rollback()
			return  err
		} else {
			// jenkins job不存在 不认为是异常
			err = nil
		}
	}

	// 事务提交
	tx.Commit()
	return
}



//@author: heyibo
//@function: UpdateDeployAppConfigure
//@description: 更改应用的配置信息
//@param: DeployApp model.DeployAppConfigure
//@return:err error, DeployApp model.DeployAppConfigure

func UpdateDeployAppConfigure(data request.UpdateDeployAppConfigureFrom) (err error) {
	var jenkins model.DeployAppJenkins
	var apps []model.DeployAppConfigure
	var total int64
	if data.DeployAppConfigure.AppsType == "common" || data.DeployAppConfigure.AppsType == "apk" {
		err = global.GVA_DB.Where("apps_job_name = ?",data.DeployAppConfigure.AppsJobName).Find(&jenkins).Count(&total).Error
		if total > 0 {
			data.DeployAppConfigure.DeployStatus = "2"
		}
		err = global.GVA_DB.Where("apps_job_name = ? AND id != ?",data.DeployAppConfigure.AppsJobName,data.DeployAppConfigure.ID).Find(&apps).Count(&total).Error
		if total >= 1 {
			return errors.New("存在相同应用Job名称")
		}
		// 通过唯一ID进行更新
		err = global.GVA_DB.Where("id = ?", data.DeployAppConfigure.ID).First(&model.DeployAppConfigure{}).Updates(&data.DeployAppConfigure).Error
		return err
	}
	if len(data.VirtualCodeInfos) == 0 {
		return errors.New("没有选择服务器")
	}
	tx :=global.GVA_DB.Begin()
	virtual :=request.DeployAppVirtualFrom{AppsJobName: data.DeployAppConfigure.AppsJobName,VirtualCodeInfos: data.VirtualCodeInfos}
	if err =UpdateDeployAppVirtual(virtual);err != nil {
		tx.Rollback()
		return err
	}
	err = global.GVA_DB.Where("apps_job_name = ?",data.DeployAppConfigure.AppsJobName).Find(&jenkins).Count(&total).Error
	if total > 0 {
		data.DeployAppConfigure.DeployStatus = "2"
	}
	err = global.GVA_DB.Where("apps_job_name = ? AND id != ?",data.DeployAppConfigure.AppsJobName,data.DeployAppConfigure.ID).Find(&apps).Count(&total).Error
	if total >= 1 {
		return errors.New("存在相同应用Job名称")
	}
	// 通过唯一ID进行更新
	err = global.GVA_DB.Where("id = ?", data.DeployAppConfigure.ID).First(&model.DeployAppConfigure{}).Updates(&data.DeployAppConfigure).Error
	if err !=nil {
		tx.Rollback()
		return err
	}
	tx.Commit()
	return err

}

//@author: heyibo
//@function: CopyDeployAppConfigure
//@description: 复制一个应用
//@param: copyInfo response.SysAuthorityCopyResponse
//@return: err error, configure model.DeployAppConfigure

func CopyDeployAppConfigure(id uint,env string) (err error) {
    var configure model.DeployAppConfigure
	if errors.Is(global.GVA_DB.Model(&model.DeployAppConfigure{}).Where("id = ?", id).First(&configure).Error, gorm.ErrRecordNotFound) {
		return gorm.ErrRecordNotFound
	}
	configure.ID = 0
	configure.AppsJobName = fmt.Sprintf("%s-%s", env, configure.AppsName)
	configure.DeployEnv = env
	if !errors.Is(global.GVA_DB.Where("apps_job_name =  ?", configure.AppsJobName).First(&model.DeployAppConfigure{}).Error, gorm.ErrRecordNotFound) {
		return errors.New("存在相同应用Job名称")
	}
	configure.DeployStatus = "0"
	return global.GVA_DB.Create(&configure).Error
}

//@author: heyibo
//@function: GetDeployAppConfigureInfoList
//@description: 分页获取数据
//@param: info request.PageInfo
//@return: err error, list interface{}, total int64

func GetDeployAppConfigureInfoList(info request.SearchDeployAppConfigureParams) (err error, list interface{}, total int64) {
	limit := info.PageSize
	offset := info.PageSize * (info.Page - 1)
	db := global.GVA_DB.Model(&model.DeployAppConfigure{})
	var appList []model.DeployAppConfigure

	if info.AppsName != "" {
		db = db.Where("apps_name = ?", info.AppsName)
	}
	if info.AppsJobName != "" {
		db = db.Where("apps_job_name = ?", info.AppsJobName)
	}
	if info.DeployEnv !="" {
		db = db.Where("deploy_env = ?",info.DeployEnv)
	}

	err = db.Count(&total).Error

	if err != nil {
		return err, appList, total
	} else {
		err = db.Limit(limit).Offset(offset).Preload("DeployAppVirtual").Preload("AppsJenkins").Preload("Projects").Find(&appList).Error
	}
	return err, appList, total
}

//@author: heyibo
//@function: UpdateDeployAppVirtual
//@description: 更新应用、环境、服务器关联表
//@return: err error, applyVirtual model.DeployAppVirtual
func UpdateDeployAppVirtual(applyVirtual request.DeployAppVirtualFrom) (err error) {
	var ClearApplyVirtual []model.DeployAppVirtual
	err = global.GVA_DB.Model(&model.DeployAppVirtual{}).Where("apps_job_name = ? ",applyVirtual.AppsJobName).Find(&ClearApplyVirtual).Error
	if len(ClearApplyVirtual) > 0 {
		if err =global.GVA_DB.Model(&model.DeployAppVirtual{}).Where("apps_job_name = ?",applyVirtual.AppsJobName).Delete(ClearApplyVirtual).Error;err !=nil{
			return errors.New("删除项目服务器配置错误！")
		}
	}
	for _, v := range applyVirtual.VirtualCodeInfos {
		virtual := model.DeployAppVirtual{
			AppsJobName: applyVirtual.AppsJobName,
			VirtualCode: v.VirtualCode,
		}
		err = global.GVA_DB.Create(&virtual).Error
		if err != nil {
			break
		}
	}
	return err
}


//@author: heyibo
//@function: GetDeployAppTree
//@description: 获取持续集成项目树
//@return: err error, menus []model.DeployApp
func GetAppProjectAuthList(casbin request.ProjectCasbinInReceive) (err error, list interface{}, total int64) {
	// 处理成字符串切片
	var projectArray []string
	limit := casbin.PageSize
	offset := casbin.PageSize * (casbin.Page - 1)
	var List []model.CMDBProject
	db := global.GVA_DB.Model(&model.CMDBProject{})
	for _, v :=range casbin.ProjectCasbinInfos {
		projectArray= append(projectArray, v.ProjectCode)
	}
	err = db.Where("project_code IN ?",projectArray).Count(&total).Error

	if err != nil {
		return err, List, total
	} else {
		if casbin.SearchKey == "" {
			db = db.Limit(limit).Offset(offset)
		}
		err = db.Where("project_code IN ?",projectArray).Find(&List).Error
		// 增加搜索功能  可通过 中文名 和project_code 进行搜索
		if casbin.SearchKey != "" {
			var ListSearch []model.CMDBProject
			for _, project := range List {
				// 不区分大小写 匹配
				if strings.Contains(strings.ToLower(project.ProjectCode), strings.ToLower(casbin.SearchKey)) ||  strings.Contains(project.ProjectFullName, casbin.SearchKey) {
					ListSearch = append(ListSearch, project)
				}
			}
			return err, ListSearch, int64(len(ListSearch))
		} else {

		}

	}
	return err, List, total
}